package com.example.studentportrait.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.studentportrait.constants.SystemConstants;
import com.example.studentportrait.domain.ResponseResult;
import com.example.studentportrait.domain.dto.*;
import com.example.studentportrait.domain.entity.*;
import com.example.studentportrait.domain.vo.AdminListVo;
import com.example.studentportrait.domain.vo.PageVo;
import com.example.studentportrait.domain.vo.PictureUserLoginVo;
import com.example.studentportrait.domain.vo.UserInfoVo;
import com.example.studentportrait.enums.AppHttpCodeEnum;
import com.example.studentportrait.exception.SystemException;
import com.example.studentportrait.mapper.RoleMapper;
import com.example.studentportrait.mapper.UserMapper;
import com.example.studentportrait.service.*;
import com.example.studentportrait.utils.BeanCopyUtils;
import com.example.studentportrait.utils.JwtUtil;
import com.example.studentportrait.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;  // 假设存在 UserRoleService 用来查询 user_role 表

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private RedisCache redisCache;
    @Resource
    UserMapper userMapper;
    @Resource
    RoleMapper roleMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private RolePermissionService rolePermissionService;

    @Autowired
    private EmployerService employerService;

    //注册
    @Transactional
    @Override
    public ResponseResult register(User user) {
        //        判断数据是否为空
        if(!StringUtils.hasText(user.getAccount())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if(!StringUtils.hasText(user.getEmail())){
            throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        if(!StringUtils.hasText(user.getPassword())){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }

        try {
            //        对密码加密
            user.setPassword(passwordEncoder.encode(user.getPassword()));
//        存入数据
            save(user);

            // 1. 存入招聘方表
            Employer employer = BeanCopyUtils.copyBean(user, Employer.class);
            // 设置招聘方表字段
            employerService.save(employer);

            // 2. 根据权限类型为1查询角色（这里权限类型为1表示管理员）
            LambdaQueryWrapper<Permission> permissionQuery = new LambdaQueryWrapper<>();
            permissionQuery.eq(Permission::getPermissionType, SystemConstants.BOSS_SIDE); // 权限类型为1
            Permission permission = permissionService.getOne(permissionQuery);

            if (permission == null) {
                throw new SystemException(AppHttpCodeEnum.CONTENT_NOT_NULL);
            }

            // 3. 根据权限查询角色权限表，获取对应的角色ID
            LambdaQueryWrapper<RolePermission> rolePermissionQuery = new LambdaQueryWrapper<>();
            rolePermissionQuery.eq(RolePermission::getPermissionId, permission.getId());
            List<RolePermission> rolePermissions = rolePermissionService.list(rolePermissionQuery);

            if (rolePermissions.isEmpty()) {
                throw new SystemException(AppHttpCodeEnum.CONTENT_NOT_NULL);
            }

            // 随机选择一个招聘方权限的角色ID
            Long selectedRoleId = rolePermissions.get(new Random().nextInt(rolePermissions.size())).getRoleId();

            // 4. 存入用户角色表
            UserRole userRole = new UserRole();
            userRole.setAccount(user.getAccount());
            userRole.setRoleId(selectedRoleId);
            userRoleService.save(userRole);
        }catch (Exception e){
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
        }
        return ResponseResult.okResult();
    }


    //登录
    @Override
    public ResponseResult login(UserDto user) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getAccount(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        System.out.println(authenticate);

        //        判断是否认证通过
        // 从Redis中获取验证码
        String verify=user.getVerifyCode();
        String codeInRedis = (String) redisTemplate.opsForValue().get("verify:" + verify);
        // 比较Redis中的验证码和前端传过来的验证码
        if (verify.equals(codeInRedis)) {
            // 验证码匹配，处理登录请求
        } else {
            // 验证码不匹配，返回错误响应
            throw new RuntimeException("验证码错误");
        }

        if (Objects.isNull(authenticate)) {
            System.out.println("密码错误");
            throw new RuntimeException("登陆失败");
        } else {
            //使用userid生成token
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            String userAccount = loginUser.getUser().getAccount().toString();
            String jwt = JwtUtil.createJWT(userAccount);
            //authenticate存入redis
            redisCache.setCacheObject("login:" + userAccount, loginUser);
            System.out.println(jwt);

            //        使用bean复制将user转换成UserInfoVo
            UserInfoVo userInfoVo = BeanCopyUtils.copyBean(loginUser.getUser(), UserInfoVo.class);

            // 使用 userAccount 查询用户角色表，获取唯一的角色 ID
            LambdaQueryWrapper<UserRole> userRoleQuery = new LambdaQueryWrapper<>();
            userRoleQuery.eq(UserRole::getAccount, userAccount);
            UserRole userRole = userRoleService.getOne(userRoleQuery);

            if (userRole == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "未找到用户角色信息");
            }

            // 获取角色 ID
            Long roleId = userRole.getRoleId();

            // 根据角色 ID 查询角色权限表，获取唯一的权限 ID
            LambdaQueryWrapper<RolePermission> rolePermissionQuery = new LambdaQueryWrapper<>();
            rolePermissionQuery.eq(RolePermission::getRoleId, roleId);
            RolePermission rolePermission = rolePermissionService.getOne(rolePermissionQuery);

            if (rolePermission == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "未找到角色权限信息");
            }

            // 获取权限 ID
            Long permissionId = rolePermission.getPermissionId();

            // 根据权限 ID 查询权限表，获取权限类型
            Permission permission = permissionService.getById(permissionId);

            if (permission == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "未找到权限信息");
            }

            // 获取权限类型
            Integer permissionType = permission.getPermissionType();

            // 将权限类型设置到 userInfoVo 的 permissionType 字段
            userInfoVo.setPermissionType(permissionType);

            //        封装用户信息和token返回
            PictureUserLoginVo pictureUserLoginVo=new PictureUserLoginVo(jwt,userInfoVo);
            return ResponseResult.okResult(pictureUserLoginVo);
        }
    }


    //后台管理员查询
    @Override
    public ResponseResult adminList(Integer pageNum, Integer pageSize, ListUserDto listUserDto) {
        // 查询基础用户信息
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getIsDelete, 0);
        lqw.eq(StringUtils.hasText(listUserDto.getAccount()), User::getAccount, listUserDto.getAccount());
        lqw.eq(StringUtils.hasText(listUserDto.getSchoolName()), User::getSchoolCode, listUserDto.getSchoolName());
        lqw.eq(listUserDto.getStatus() != null, User::getStatus, listUserDto.getStatus());

        // 分页查询
        Page<User> page = new Page<>(pageNum, pageSize);
        page(page, lqw);

        // 获取查询结果
        List<User> userList = page.getRecords();

        if (userList.isEmpty()) {
            return ResponseResult.okResult(new PageVo(Collections.emptyList(), 0L));
        }

        // 根据权限类型 3 查询权限表获取权限 ID
        LambdaQueryWrapper<Permission> permissionQuery = new LambdaQueryWrapper<>();
        permissionQuery.eq(Permission::getPermissionType, SystemConstants.COMMON_SIDE);
        Permission permission = permissionService.getOne(permissionQuery);

        if (permission == null) {
            return ResponseResult.okResult(new PageVo(Collections.emptyList(), 0L));
        }

        Long permissionId = permission.getId();

        // 根据权限 ID 查询角色权限表获取对应角色 ID
        LambdaQueryWrapper<RolePermission> rolePermissionQuery = new LambdaQueryWrapper<>();
        rolePermissionQuery.eq(RolePermission::getPermissionId, permissionId);
        List<RolePermission> rolePermissions = rolePermissionService.list(rolePermissionQuery);

        if (rolePermissions.isEmpty()) {
            return ResponseResult.okResult(new PageVo(Collections.emptyList(), 0L));
        }

        // 获取角色 ID 集合
        Set<Long> roleIds = rolePermissions.stream()
                .map(RolePermission::getRoleId)
                .collect(Collectors.toSet());

        // 根据角色 ID 查询用户角色表筛选出对应的用户
        List<String> userAccounts = userList.stream().map(User::getAccount).collect(Collectors.toList());
        LambdaQueryWrapper<UserRole> userRoleQuery = new LambdaQueryWrapper<>();
        userRoleQuery.in(UserRole::getAccount, userAccounts)
                .in(UserRole::getRoleId, roleIds);
        List<UserRole> userRoles = userRoleService.list(userRoleQuery);

        if (userRoles.isEmpty()) {
            return ResponseResult.okResult(new PageVo(Collections.emptyList(), 0L));
        }

        // 获取筛选后的用户账号和对应角色 ID
        Map<String, Long> accountRoleMap = userRoles.stream()
                .collect(Collectors.toMap(UserRole::getAccount, UserRole::getRoleId));

        // 查询角色表获取角色 ID 和角色名的映射
        LambdaQueryWrapper<Role> roleQuery = new LambdaQueryWrapper<>();
        roleQuery.in(Role::getId, roleIds);
        List<Role> roles = roleService.list(roleQuery);
        Map<Long, String> roleNameMap = roles.stream()
                .collect(Collectors.toMap(Role::getId, Role::getRoleName));

        // 筛选并设置用户角色名
        List<AdminListVo> userVos = userList.stream()
                .filter(user -> accountRoleMap.containsKey(user.getAccount()))
                .map(user -> {
                    AdminListVo vo = BeanCopyUtils.copyBean(user, AdminListVo.class);
                    Long roleId = accountRoleMap.get(user.getAccount());
                    vo.setRoleName(roleNameMap.getOrDefault(roleId, "Unknown")); // 设置角色名
                    return vo;
                })
                .collect(Collectors.toList());
        //TODO 根据学校编号查学校表拿到学校名填入学校名字段
// 更新总条数为筛选后的记录数
        long filteredTotal = userVos.size();
        // 返回分页结果
        PageVo pageVo = new PageVo(userVos, filteredTotal);
        return ResponseResult.okResult(pageVo);
    }



    //新增管理员
    @Transactional
    @Override
    public ResponseResult addAdmin(AddAdminDto addAdminDto) {
        // 1. 将传入的数据存入用户表
        addAdminDto.setAccount(passwordEncoder.encode(addAdminDto.getPassword()));
        User user = BeanCopyUtils.copyBean(addAdminDto, User.class);
        boolean userSaved = save(user); // 保存用户

        if (!userSaved) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "新增用户失败");
        }

        // 2. 将 addAdminDto 里的 account 和 roleId 存入用户角色表
        UserRole userRole = new UserRole();
        userRole.setAccount(addAdminDto.getAccount());
        userRole.setRoleId(addAdminDto.getRoleId());
        boolean userRoleSaved = userRoleService.save(userRole); // 保存用户角色

        if (!userRoleSaved) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "新增用户角色失败");
        }

        return ResponseResult.okResult("新增管理员成功");
    }

    //编辑管理员
    @Override
    public ResponseResult updateAdmin(UpdateAdminDto updateAdminDto) {
        // 更新用户表
        LambdaUpdateWrapper<User> userUpdateWrapper = new LambdaUpdateWrapper<>();
        userUpdateWrapper.eq(User::getAccount, updateAdminDto.getAccount()); // 根据账号匹配
        if (StringUtils.hasText(updateAdminDto.getEmail())) {
            userUpdateWrapper.set(User::getEmail, updateAdminDto.getEmail()); // 更新邮箱
        }
        if (StringUtils.hasText(updateAdminDto.getPassword())) {
            // 密码加密处理
            String encryptedPassword = passwordEncoder.encode(updateAdminDto.getPassword());
            userUpdateWrapper.set(User::getPassword, encryptedPassword); // 更新密码
        }
        if (updateAdminDto.getStatus() != null) {
            userUpdateWrapper.set(User::getStatus, updateAdminDto.getStatus()); // 更新状态
        }

        boolean userUpdated = update(userUpdateWrapper); // 执行用户表更新操作

        if (!userUpdated) {
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR); // 如果更新失败，抛出异常
        }

        // 更新用户角色表
        LambdaUpdateWrapper<UserRole> userRoleUpdateWrapper = new LambdaUpdateWrapper<>();
        userRoleUpdateWrapper.eq(UserRole::getAccount, updateAdminDto.getAccount()) // 根据账号匹配
                .set(UserRole::getRoleId, updateAdminDto.getRoleId()); // 更新角色ID

        boolean roleUpdated = userRoleService.update(userRoleUpdateWrapper); // 执行角色表更新操作

        if (!roleUpdated) {
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR); // 如果更新失败，抛出异常
        }

        // 如果一切正常，返回成功结果
        return ResponseResult.okResult();
    }


}
